<template>
    <div>
        <pre v-note>
        路由的实现方案(SPA)：
            1、通过修改URL地址记录当前模块项目中需要展示的组件是哪个
            2、通过监听地址变化，动态修改vue中动态组件componet 的is 取值，完成类似的页面切换效果

        vue-router 模块就是一个实现了上述描述的特殊地址控制组件切换的功能模块

        vue模块化项目的路由安装和集成
            1. 自动化安装集成（安装模块+修改文件+修改配置）
                在项目创建时(vue create)就完成 Router 模块的选择
            2. 手动化安装集成
                + 下载vue路由模块 npm install vue-router@3.5.1 -S
                + 在模块化项目中完成路由模块在 mian.js 的导入 import VueRouter from 'vue-router'
                + 为vue的模块化项目通过 Vue.use(VueRouter) 扩充路由功能（路由的初始化，路由组件的定义，路由对象的记录）
                + vue-router 的路由实例提供 new VueRouter() 进行路由实例创建
                + Vue.use(VueRouter) 
                    => 为vue模块项目的 new Vue 提供一个新的路由配置选项 router，该选项取值路由实例
                    => 为vue路由模块化项目提供两个全局组件 RouterView RouterLink
                       RouterView 是路由二次封装的，具有导航变化监听的动态组件，会自动根据出现的位置选择显示对应的路由组件
                       RouterLink 是路由开发定义的，具有导航修改功能的切换组件，并相应的激活样式
                    => 为vue构造器提供原型只读属性 $route，该属性用于记录当前激活路由的相关信息(激活路由信息对象)
                    => 为vue构造器提供原型只读属性 $router，该属性为当前项目加载的路由对象，该对象包含路由操作方法(路由控制对象)
                + new VueRouter(routerConfig) , routerConfig 取值为对象，用于定义路由功能和地址与组件的对应关系
                <code>
                routerConfig = {
                    // 配置导航组件在激活时(激活路由)增加的样式名，可以通过配置方式修改
                    linkActiveClass:"router-link-active",
                    linkExactActiveClass:"router-link-exact-active",
                    base:"路由基础前缀地址"
                    // hash 锚点技术实现 => 地址上会出现 #
                    // history 通过 history.pushState 方法实现的 => 地址上不存在 #
                    //          ==> 该模式完成的项目生产部署，在刷新页面时可能会造成服务器404资源丢失的问题
                    //          ==> 该问题需要通过修改服务器配置进行处理，参考 <a href="https://v3.router.vuejs.org/zh/guide/essentials/history-mode.html#%E5%90%8E%E7%AB%AF%E9%85%8D%E7%BD%AE%E4%BE%8B%E5%AD%90" style="color:#fff">服务器配置</a>
                    mode:"hash | history | abstract",
                    // 路由表 = 定义组件对应的 url 地址名称
                    routes＜route＞:[
                        {
                            // 一级路由地址必须以 / 开头
                            //      1. 如果一级路由定义地址取值 / 表示项目的默认页面
                            //      2. 如果取值为关键字 * 作为占位(vue-router@3)，表示所有未被匹配的其它地址，该地址必须为最后一个路由表配置
                            // 子路由配置可以以 / 开头，也可以不以 / 开头
                            //      1. 绝对路由地址 : 以项目的最终部署目录作为根目录进行地址描述，定义导航时无需关系父路由地址
                            //      2. 相对路由地址 : 以父路由地址为基础参考地址，完成路由地址拼接，定义导航时必须注意携带父路由地址
                            //      3. 子路由的默认地址为 “” 字符串
                            path : "组件的对应地址",
                            name : "当前路由的导航操作别名"
                            // 取值为单文件组件的 导出数据
                            component : 地址对应的组件配置,
                            // 路由重定向
                            redirect : 路由中已经定义的其他地址,
                            // 配置当前路由的子路由
                            children : Array＜route＞,
                            // 路由元信息
                            // meta 属性在构建路由时,为当前路由自定义配置项,用于页面特殊构成的配置
                            meta:{}
                        }
                    ]
                }
                </code>
        </pre>
        <br>
        <pre v-note>
        路由模式切换和定义
            通过配置 mode 取值，可修改路由模式
                1. hash模式 ： 以 html 中 锚点技术实现的 路由匹配切换
                    锚点 可以更改 url地址的同时 ，不刷新页面的方式实现
                    通过 window.location.hash 获取 锚点值，通过锚点值 匹配组件，进行渲染展示
                2. history 模式 ： 历史地址模式 - 必须配合 base 属性进行定义前缀描述和加载
                    该模式不能单独使用，必须需要后台通过代码进行 配合使用
                    将地址转换为正常的 URL地址，使用JS 的URL地址栏 history API 实现页面不刷新组件更新的效果
        </pre>
        <br>
        <pre v-note>
        路由地址定义
            1. 基本地址定义
                通过配置path属性描述组件和地址关系，一级路由定义时必须使用`/`开头，子级路由可选择绝对路径或相对路径
            2. 默认地址定义
                vue路由默认展示地址为 / 的组件，因此以path:"/" 描述默认组件
                默认地址一般使用路由定向方式跳转到其它组件上：{path:"/"，redirect："目标地址"}
            3. 通配地址定义
                对没有在路由表中定义的路径，vue会进行统一的地址处理**
                通过配置path通配符 *，描述路由表中不存在的地址默认访问的组件
                    + {path:"/*"，redirect："目标地址"}`
                    + {path:"/*"，component：组件}
        </pre>
        <br>
        <pre v-note>
        激活路由样式控制
            Vue.use(VueRouter) 提供两个用于描述激活路由样式的class样式名
                1. .router-link-active 样式
                    + 该样式被自动定义在＜router-link＞标签上
                    + 样式随着激活路由的变化，选择出现在路径中包含当前路径的＜router-link＞标签上
                2. .router-link-exact-active 样式 
                    + 该样式被自动定义在＜router-link＞标签上
                    + 样式随着激活路由的变化，选择出现在路径完全相同的＜router-link＞标签上
        </pre>
        <pre v-note>
        激活路由信息对象 $route
            Vue.use(VueRouter) 提供组件Vue构造器原型属性 $route
                + 路由模块通过对 Vue 原型的修改，为所有 vue实例的增加一个原型变量 $route
                + $route 是激活路由信息对象，存储当前激活路由的相关信息
                + $route 为组件共享数据仓库，所有组件的route 都是同一个对象
                + $route 为只读对象，无法被修改
                + $route 信息对象中记录了与激活路由相关的配置属性，其中参数传递数据被分别包含于 query 和 params中
                    - URL地址参数：在路由地址后以 ? = & 符合组成的参数，通过 $route.query 进行加载
                    - REST地址参数：采用resfull接口技术的地址隐藏参数，通过 $route.params 进行加载
        路由控制对象 $router
            Vue.use(VueRouter) 提供组件Vue构造器原型属性 $router
                + 路由模块通过对 Vue 原型的修改，为所有 vue实例的增加一个原型变量 $router
                + $router 是当前vue项目集成的 路由实例对象(new VueRouter)，该对象包含了路由所有的配置和操作方法，所以也被叫做路由控制对象
                + $router 对象内置路由切换方法
                    - $router.go(n)  在浏览器历史记录中前进 n 个地址
                    - $router.forward() 在浏览器历史记录中前进 1 个地址
                    - $router.back()  在浏览器历史记录中后退 1 个地址
                    - $router.push(to)  在当前项目中以新路由的方式切换页面，等效于 router-link 的默认功能
                                        to参数 等效于 router-link 的 to 属性
                                        在浏览器的历史中添加新的历史记录 
                    - $router.replace()  在浏览器中对当前历史记录进行替换
        </pre>
        <hr>
        <h5>路由信息对象</h5>
        <input type="button" value="打印激活路由信息对象" @click="printRoute()">
        <h5>子路由</h5>
        <router-link class="btn" to="/one">子路由one-绝对路由地址</router-link>
        <router-link class="btn" to="/router/two">子路由two-相对路由地址</router-link>
        <h5>路由切换参数-URL参数</h5>
       
        <!-- <img src="@/assets/Snipaste_2022-08-13_09-14-30.png" style="width:500px"> <br> -->
        <router-link class="btn" to="/router/three?sid=100001">子路由three-张三-静态绑定</router-link>
        <router-link class="btn" to="/router/three?sid=100002&a=测试">子路由three-李四</router-link>
        <router-link class="btn" to="/router/three">子路由three-不存在</router-link>
        <h5>路由切换参数-仿resfull请求的rest参数-动态路由</h5>
        <router-link class="btn" to="/router/four/100001">子路由four-张三-只有ID</router-link>
        <router-link class="btn" to="/router/four/100001/第二个参数">子路由four-张三-有ID&info</router-link>
        <router-link class="btn" to="/router/four/100002">子路由four-李四</router-link>
        <router-link class="btn" to="/router/four">子路由子路由four-不存在</router-link>
        <h5>vue路由动态绑定参数</h5>
        <p>id:{{ id }}</p>
        <!-- <select v-model="urlObj.query.sid">
            <option value="">请选择</option>
            <option value="100001">张三</option>
            <option value="100002">李四</option>
        </select> -->
        <select v-model="id">
            <option value="">请选择</option>
            <option value="100001">张三</option>
            <option value="100002">李四</option>
        </select><br>
        <router-link class="btn" :to="`/router/three?sid=${id}`">子路由three-URL参数-动态绑定-String</router-link><br>
        <router-link class="btn" :to="urlObj">子路由three-URL参数-动态绑定-Object-仓库对象-使用path路径路由</router-link><br>
        <router-link class="btn" 
            :to="{
                path:'/router/three',
                query:{
                    sid:id
                }
            }"
        >子路由three-URL参数-动态绑定-Object-匿名对象-使用path路径路由</router-link><br>
        <router-link class="btn" 
            :to="{
                name:'three',
                query:{
                    sid:id
                }
            }"
        >子路由three-URL参数-动态绑定-Object-匿名对象-使用name具名路由</router-link><br>
        <br>
        <router-link class="btn" :to="`/router/four/${id}`">子路由four-REST参数-动态绑定-String</router-link><br>
        <router-link class="btn" 
            :to="{
                name:'four',
                params:{
                    sid:id,
                    info:'测试数据'
                }
            }"
        >子路由four-REST参数-动态绑定-Object-匿名对象-只能使用name具名路由</router-link><br>
        <router-link class="btn" 
            :to="{
                name:'four'
            }"
        >子路由four-REST参数-无参数</router-link><br>
        <hr>
        <h4>编程式导航</h4>
        <input type="button" value="访问需要授权的页面" @click="gotoToke()">
        <!-- <router-link to="/router/token" tag="button">访问需要授权的页面</router-link> -->
        <br>
        <h4>路由缓存和守卫</h4>
        <router-link class="btn" to="/router/five?arg=11111">路由缓存-url参数1</router-link>
        <router-link class="btn" to="/router/five?arg=22222">路由缓存-url参数2</router-link>
        <hr>
        <router-view></router-view>
    </div>
</template>

<script>
export default {
    data() {
        return {
            id:"",
            urlObj:{
                path:"/router/three",
                query:{
                    sid:"100002",
                    name:"aaaa",
                    aaa:"11111",
                    bbb:"22222"
                }
            }
        }
    },
    // watch:{
    //     id(nv){
    //         this.urlObj.query.sid = nv;
    //     }
    // },
    methods:{
        printRoute(){
            console.log( "$route:",this.$route )
        },
        gotoToke(){
            console.log( "$router:",this.$router )
            // this.$router.go(n)  // 在浏览器历史记录中前进 n 个地址
            // this.$router.forward() // 在浏览器历史记录中前进 1 个地址
            // this.$router.back() // 在浏览器历史记录中后退 1 个地址
            // this.$router.push(to) // 在当前项目中以新路由的方式切换页面，等效于 router-link 的默认功能
                                     // to参数 等效于 router-link 的 to 属性
                                     // 在浏览器的历史中添加新的历史记录 

            // this.$router.replace() // 在浏览器中对当前历史记录进行替换
            // this.$router.replace("/router/token")  // 一般用于必须从指定入口进行方法的页面跳转

            // this.$router.push("/router/token")
            // this.$router.push({
                //     path:"/router/token"
            // })

            // 判断
            let token = sessionStorage.getItem("token")
            if(token){
                this.$router.push({
                    name:"token"
                })
            }else{
                 this.$router.push({
                    name:"login",
                    params:{
                        msg:"请先登录",
                        path:"token"
                    }
                })
            }
        }
    }
}
</script>

<style scoped>
.btn{
    padding: 0px 10px;
}
</style>